package cn.nkpro.elcube.task.from;

import cn.nkpro.elcube.basic.NkProperties;
import cn.nkpro.elcube.co.NkCustomScriptHelper;
import cn.nkpro.elcube.co.NkCustomScriptObject;
import cn.nkpro.elcube.co.NkScriptV;
import cn.nkpro.elcube.co.spel.NkSpELManager;
import cn.nkpro.elcube.platform.model.NkSelectItem;
import cn.nkpro.elcube.task.model.BpmFormField;
import com.alibaba.fastjson.JSON;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang3.StringUtils;
import org.camunda.bpm.engine.ProcessEngine;
import org.camunda.bpm.engine.impl.form.type.AbstractFormFieldType;
import org.camunda.bpm.engine.task.Task;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.expression.EvaluationContext;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

public abstract class NkAbstractFormFieldType extends AbstractFormFieldType implements NkCustomFormFieldType, NkCustomScriptObject, InitializingBean {

    @Autowired
    private NkProperties properties;
    @Getter
    protected String beanName;
    @Autowired
    protected NkSpELManager spELManager;
    @Autowired@Lazy
    protected ProcessEngine processEngine;

    @Setter
    @Getter
    protected NkScriptV scriptDef;

    public NkAbstractFormFieldType() {
        this.beanName = NkCustomScriptHelper.parseComponentName(getClass());
    }

    @Override
    public final String getName() {
        return beanName;
    }

    @Override
    public Map<String,String> getVueTemplate(){

        NkScriptV scriptDef = this.scriptDef;;
        if(!this.scriptDef.isDebug() && properties.isComponentReloadClassPath()){
            scriptDef = NkCustomScriptHelper.loadScriptFromClassPath(properties.getComponentBasePackages(),getClass(),beanName);
        }

        Map<String,String> vueMap = new HashMap<>();
        if(StringUtils.isNotBlank(scriptDef.getVueMain())){
            vueMap.put(scriptDef.getScriptName(),scriptDef.getVueMain());
        }
        return vueMap;
    }

    @Override
    public final void preprocess(BpmFormField field, Task task) {

        AtomicReference<EvaluationContext> context = new AtomicReference<>();
        field.getProperties().forEach( (k,v) -> {
            if(spELManager.hasTemplate(v)){
                if(context.get()==null){
                    context.set(spELManager.createContext(processEngine.getRuntimeService().getVariables(task.getExecutionId())));
                }
                field.getProperties().put(k,JSON.parseObject(spELManager.convert(v, context.get()),String.class));
            }
        });
        this.doPreprocess(field, task);
    }

    protected void doPreprocess(BpmFormField field, Task task){

    }

    public final void afterPropertiesSet(){
        if(this.scriptDef==null){
            // 从classpath中加载资源
            this.scriptDef = NkCustomScriptHelper.loadScriptFromClassPath(properties.getComponentBasePackages(),getClass(),beanName);
        }
    }

}
